package xcmg.device.service.agent;

import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.PriMaterialsDO;
import xcmg.device.dao.entity.agent.ServiceBorrowOutDO;
import xcmg.device.dao.entity.agent.ServiceBorrowOutDetailDO;
import xcmg.device.dao.entity.repair.RepairDO;
import xcmg.device.dao.entity.warehouse.WarehouseDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseInventoryDO;
import xcmg.device.dao.mapper.CompanyDealerMapper;
import xcmg.device.dao.mapper.MarketingMaterialsMapper;
import xcmg.device.dao.mapper.MaterialLocationRelationMapper;
import xcmg.device.dao.mapper.PriMaterialsMapper;
import xcmg.device.dao.mapper.agent.ServiceBasicDataAgentMapper;
import xcmg.device.dao.mapper.agent.ServiceBorrowInDetailMapper;
import xcmg.device.dao.mapper.agent.ServiceBorrowOutDetailMapper;
import xcmg.device.dao.mapper.agent.ServiceBorrowOutMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseAreaLocationDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryDetailMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInventoryMapper;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.infra.exception.CommonBusiExceptions;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.basic.CommonGenService;
import xcmg.device.service.marketing.MarketingActivityService;
import xcmg.device.service.repair.RepairService;
import xcmg.device.service.vo.agent.ServiceBorrowInAddVO;
import xcmg.device.service.vo.agent.ServiceBorrowInDetailVO;
import xcmg.device.service.vo.agent.ServiceBorrowInVO;
import xcmg.device.service.vo.agent.ServiceBorrowOutDetailVO;
import xcmg.device.service.vo.agent.ServiceBorrowOutVO;
import xcmg.device.service.vo.agent.ServiceBorrowingVO;
import xcmg.device.service.vo.basic.MaterialLocationRelationVO;
import xcmg.device.service.vo.marketing.MarketingActivityPriceVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryRecordAddVO;
import xcmg.device.service.vo.warehouse.app.EnableAndOccupyVO;
import xcmg.device.service.warehouse.WarehouseDeliveryRecordService;
import xcmg.device.service.warehouse.WarehouseDeliveryService;
import xcmg.device.service.warehouse.WarehouseInventoryService;
import xcmg.device.util.CompanyUtil;
import yb.ecp.fast.dto.UserCacheDTO;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;


/**
 * ServiceBorrowOut 后台接口实现类
 *
 * @author huhuawei
 */
@Service
public class ServiceBorrowOutService {


    private static final Logger logger = LoggerFactory.getLogger(ServiceBorrowOutService.class);
    @Autowired
    private HttpServletResponse response;

    @Autowired
    private CommonGenService commonGenService;
    @Autowired
    private ServiceBorrowOutMapper serviceBorrowOutMapper;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private ServiceBorrowOutDetailService serviceBorrowOutDetailService;

    @Autowired
    private WarehouseDeliveryService warehouseDeliveryService;

    @Autowired
    private ServiceBorrowOutDetailMapper serviceBorrowOutDetailMapper;

    @Autowired
    private WarehouseDeliveryDetailMapper warehouseDeliveryDetailMapper;

    @Autowired
    private WarehouseDeliveryMapper warehouseDeliveryMapper;

    @Autowired
    private ServiceBorrowingService serviceBorrowingService;

    @Autowired
    private ServiceStaffQuotaService serviceStaffQuotaService;
    @Autowired
    private ServiceBorrowInDetailMapper serviceBorrowInDetailMapper;
    @Autowired
    private MarketingActivityService marketingActivityService;
    @Autowired
    private MaterialLocationRelationMapper materialLocationRelationMapper;
    @Autowired
    private WarehouseInventoryService warehouseInventoryService;

    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;

    @Autowired
    private WarehouseAreaLocationDOMapper warehouseAreaLocationDOMapper;

    @Autowired
    private WarehouseDOMapper warehouseDOMapper;

    @Autowired
    private PriMaterialsMapper materialMapper;

    @Autowired
    private MarketingMaterialsMapper marketingMaterialsMapper;

    @Autowired
    private CompanyUtil companyUtil;

    @Autowired
    private CompanyDealerMapper companyDealerMapper;

    @Autowired
    private ServiceBasicDataAgentMapper serviceBasicDataAgentMapper;

    @Autowired
    private RepairService repairService;

    @Autowired
    private WarehouseDeliveryRecordService warehouseDeliveryRecordService;

    private final static String AGENT_RETAIL_PRICE_NAME = "代理商零售价";

    /**
     * 查询列表
     *
     * @param condition
     */
    public PageCommonVO<ServiceBorrowOutVO> list(SearchCommonVO<ServiceBorrowOutVO> condition) {
        if (null == condition.getFilters()) {
            condition.setFilters(new ServiceBorrowOutVO());
        }
        PageCommonVO<ServiceBorrowOutVO> pageCommonVO = new PageCommonVO<>();
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<ServiceBorrowOutDO> queryList = serviceBorrowOutMapper.queryList(condition.getFilters());
        List<ServiceBorrowOutVO> voList = new ArrayList<>();
        for (ServiceBorrowOutDO entity : queryList) {
            ServiceBorrowOutVO serviceBorrowOutVO = new ServiceBorrowOutVO();
            BeanUtils.copyProperties(entity, serviceBorrowOutVO);
            voList.add(serviceBorrowOutVO);
        }
        pageCommonVO.setPageInfo(new PageInfo<>(queryList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    /**
     * 查询列表
     *
     * @param vo
     */
    public List<ServiceBorrowOutDO> queryList(ServiceBorrowOutVO vo) {
        return serviceBorrowOutMapper.queryList(vo);
    }


    /**
     * 查询单条记录
     *
     * @param id
     */
    public ServiceBorrowOutVO queryById(String id, String orgId) {
        ServiceBorrowOutDO serviceBorrowOutDO = new ServiceBorrowOutDO();
        ServiceBorrowOutVO vo = new ServiceBorrowOutVO();
        vo.setId(id);
        List<ServiceBorrowOutDO> list = queryList(vo);
        if (CollectionUtils.isNotEmpty(list)) {
            serviceBorrowOutDO = list.get(0);
        }
        BeanUtils.copyProperties(serviceBorrowOutDO, vo);
        //查询借出详情数据
        ServiceBorrowOutDetailVO detailCond = new ServiceBorrowOutDetailVO();
        detailCond.setBorrowOutId(id);
        List<ServiceBorrowOutDetailDO> serviceBorrowOutDetailDOS = serviceBorrowOutDetailService.queryList(detailCond);
        List<ServiceBorrowOutDetailVO> serviceBorrowOutDetailVOS = new ArrayList<>();
        for (ServiceBorrowOutDetailDO serviceBorrowOutDetailDO : serviceBorrowOutDetailDOS) {
            ServiceBorrowOutDetailVO detailVO = new ServiceBorrowOutDetailVO();
            BeanUtils.copyProperties(serviceBorrowOutDetailDO, detailVO);
            String materialsNo = serviceBorrowOutDetailDO.getMaterialsNo();
            MarketingActivityPriceVO priceVO = marketingActivityService.getAgentRetailPrice(AGENT_RETAIL_PRICE_NAME, orgId, materialsNo);
            if (null != priceVO) {
                BigDecimal discountPrice = priceVO.getDiscountPrice();
                detailVO.setAgentRetailPrice(discountPrice);
            }
            // 获取默认储位和库存储位
            getDefaultLocationCode(orgId, vo, detailVO);
            EnableAndOccupyVO enableAndOccupyVO = warehouseInventoryService.findEnableAndOccupyNum(materialsNo, vo.getOrgId(), vo.getWarehouseCode());
            BeanUtils.copyProperties(enableAndOccupyVO, detailVO);
            BigDecimal resaleQty = getValueDefaultZero(detailVO.getResaleQty());
            BigDecimal rollBackQty = getValueDefaultZero(detailVO.getRollBackQty());
            BigDecimal outQuantity = getValueDefaultZero(detailVO.getOutQuantity());
            detailVO.setCanResaleQty(outQuantity.subtract(resaleQty).subtract(rollBackQty));
            serviceBorrowOutDetailVOS.add(detailVO);
        }
        if (StringUtils.isNotBlank(vo.getWarehouseCode())) {
            WarehouseDO warehouse = warehouseDOMapper.itemByWarehouseCode(orgId, vo.getWarehouseCode());
            if (null != warehouse) {
                vo.setWarehouseCodeDesc(warehouse.getDescription());
            }
        }

        Collections.sort(serviceBorrowOutDetailVOS, (o1, o2) -> {
            if (o1.getLocationCode() == null && o2.getLocationCode() == null) {
                return 0;
            } else if (o1.getLocationCode() == null) {
                return -1;
            } else if (o2.getLocationCode() == null) {
                return 1;
            } else {
                return o1.getLocationCode().compareTo(o2.getLocationCode());
            }
        });
        vo.setServiceBorrowOutDetailVOS(serviceBorrowOutDetailVOS);
        return vo;
    }

    public BigDecimal getValueDefaultZero(BigDecimal resaleQty) {
        return resaleQty == null ? BigDecimal.ZERO : resaleQty;
    }

    // 获取默认储位和库存储位
    private void getDefaultLocationCode(String orgId, ServiceBorrowOutVO vo, ServiceBorrowOutDetailVO detailVO) {
        MaterialLocationRelationVO condition = new MaterialLocationRelationVO();
        condition.setWarehouseCode(vo.getWarehouseCode());
        condition.setOrgId(orgId);
        condition.setMaterialNo(detailVO.getMaterialsNo());
        List<MaterialLocationRelationVO> voList = materialLocationRelationMapper.list(condition);
        if (!voList.isEmpty()) {
            detailVO.setStockLocation(voList.get(0).getLocationCode());
        }

        List<String> locationCodeList = warehouseInventoryMapper.findLocationCode(orgId, detailVO.getMaterialsNo(), vo.getWarehouseCode(), null);
        if (!locationCodeList.isEmpty()) {
            detailVO.setLocationCode(String.join(",", locationCodeList));
        }

        if (!locationCodeList.isEmpty()) {
            List<String> locationDescList = new ArrayList<>();
            for (String locationCode : locationCodeList) {
                String locationDesc = warehouseAreaLocationDOMapper.getLocationDesc(locationCode);
                locationDescList.add(locationDesc);
            }
            detailVO.setLocationDesc(String.join(",", locationDescList));
        }
    }

    /**
     * 保存数据
     *
     * @param serviceBorrowOutVO
     * @param userId
     * @param userName
     * @param orgId
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode save(ServiceBorrowOutVO serviceBorrowOutVO, String userId, String userName, String orgId) throws Exception {
        return doSave(serviceBorrowOutVO, userId, userName, orgId);
    }

    @Transactional(rollbackFor = Exception.class)
    public String syncOrder(ServiceBorrowOutVO serviceBorrowOutVO) throws Exception {
        List<ServiceBorrowOutDetailVO> detailVOs = checkParam(serviceBorrowOutVO);

        String orgId = getCompanyOrgIdByCode(serviceBorrowOutVO.getErpCode());

        String defaultWarehouseCode = checkDefaultWarehouse(orgId, serviceBorrowOutVO.getRepairNo());

        serviceBorrowOutVO.setWarehouseCode(defaultWarehouseCode);

        ServiceBorrowOutDO serviceBorrowOutDO = serviceBorrowOutMapper.selectByBorrowNo(serviceBorrowOutVO.getBorrowNo(), orgId);

        boolean addFlag = false;

        if (serviceBorrowOutDO == null) {
            addFlag = true;
        } else {
            if (!Integer.valueOf(0).equals(serviceBorrowOutDO.getStatus())) {
                throw new CommonBusiExceptions("该状态不支持修改");
            }
        }

        syncInfo(serviceBorrowOutVO, orgId);
        serviceBorrowOutDO = serviceBorrowOutMapper.selectByBorrowNo(serviceBorrowOutVO.getBorrowNo(), orgId);
        serviceBorrowOutDetailService.deleteByBorrowOutId(serviceBorrowOutDO.getId());
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (ServiceBorrowOutDetailVO detailVO : detailVOs) {
            PriMaterialsDO materialsDO = checkMaterialInfo(orgId, detailVO);
            detailVO.setOutQuantity(BigDecimal.ZERO);
            detailVO.setBorrowOutId(serviceBorrowOutDO.getId());
            detailVO.setBorrowOutNo(serviceBorrowOutDO.getBorrowNo());
            detailVO.setMaterialsDes(materialsDO.getMaterialsDes());
            detailVO.setUnit(materialsDO.getUnit());
            detailVO.setPrice(materialsDO.getPrice());
            if (detailVO.getQuantity() != null && detailVO.getPrice() != null) {
                detailVO.setSubtotalAmount(detailVO.getQuantity().multiply(detailVO.getPrice()));
            } else {
                detailVO.setSubtotalAmount(BigDecimal.ZERO);
            }
            totalAmount = totalAmount.add(detailVO.getSubtotalAmount());
            serviceBorrowOutDetailService.syncDetail(detailVO);
        }
        if (addFlag) {
            saveWarehouseDeliveryByBorrowInfo(serviceBorrowOutDO, detailVOs);
        } else {
            updateWarehouseDeliveryByBorrowInfo(serviceBorrowOutDO, detailVOs);
        }

        serviceBorrowOutMapper.updateAmount(serviceBorrowOutVO.getBorrowNo(), totalAmount);
        return serviceBorrowOutVO.getBorrowNo();
    }

    private PriMaterialsDO checkMaterialInfo(String orgId, ServiceBorrowOutDetailVO detailVO) {
        if (StringUtils.isEmpty(detailVO.getMaterialsNo())) {
            throw new CommonBusiExceptions("零件编码不能为空");
        }
        if (detailVO.getQuantity() == null) {
            throw new CommonBusiExceptions("数量不能为空");
        }
        PriMaterialsDO materialsDO = materialMapper.itemByNo(detailVO.getMaterialsNo(), orgId);
        if (materialsDO == null) {
            materialsDO = materialMapper.itemByNo(detailVO.getMaterialsNo(), companyUtil.ynOrgId());
            if (materialsDO == null) {
                throw new CommonBusiExceptions("零件不存在");
            }
            materialsDO.setOrgId(orgId);
            materialsDO.setStandardPrice(null);
            materialsDO.setPrice(null);
            materialsDO.setAgentPurchasePrice(null);
            materialsDO.setMovingAveragePrice(null);
            materialMapper.insert(materialsDO);
        }
        return materialsDO;
    }

    private String checkDefaultWarehouse(String orgId, String repairNo) {
        if (StringUtils.isNotBlank(repairNo)) {
            List<RepairDO> ll = repairService.itemByCode(repairNo);
            if (CollectionUtils.isNotEmpty(ll)) {
                return ll.get(0).getWarehouseCode();
            }
        }
        String defaultWarehouse = "DEFAULT";
        int count = warehouseDOMapper.countByWarehouseCode(orgId, defaultWarehouse);
        if (count == 0) {
            ActionResult<String> textResult = fastGenClient.textGuid();
            if (ErrorCode.Success.getCode() != textResult.getCode()) {
                throw new CommonBusiExceptions(textResult.getMessage());
            }
            WarehouseDO warehouseDO = new WarehouseDO();
            warehouseDO.setId(textResult.getValue());
            warehouseDO.setWarehouseCode(defaultWarehouse);
            warehouseDO.setOrgId(orgId);
            warehouseDO.setDescription("默认仓库");
            warehouseDO.setKeeperId("");
            warehouseDO.setIsPlan(0);
            warehouseDO.setIsCenter(0);
            warehouseDO.setFirstInOut(0);
            warehouseDO.setIsBarCode(1);
            warehouseDO.setWarehouseType(null);
            warehouseDO.setWarehouseTypeDesc(null);
            warehouseDOMapper.insert(warehouseDO);
        }

        return defaultWarehouse;
    }

    private List<ServiceBorrowOutDetailVO> checkParam(ServiceBorrowOutVO serviceBorrowOutVO) {
        if (StringUtils.isEmpty(serviceBorrowOutVO.getBorrowNo())) {
            throw new CommonBusiExceptions("维修单号不能为空");
        }

        serviceBorrowOutVO.setDispatchNo(serviceBorrowOutVO.getBorrowNo());

        serviceBorrowOutVO.setBorrowNo(BillDesc.ServiceBorrow.getDesc() + serviceBorrowOutVO.getBorrowNo());

        if (StringUtils.isEmpty(serviceBorrowOutVO.getErpCode())) {
            throw new CommonBusiExceptions("服务ERP编码不存在");
        }
        if (StringUtils.isEmpty(serviceBorrowOutVO.getEngineNo())) {
            throw new CommonBusiExceptions("发动机编号不存在");
        }
        List<ServiceBorrowOutDetailVO> detailVOs = serviceBorrowOutVO.getServiceBorrowOutDetailVOS();
        if (CollectionUtils.isEmpty(detailVOs)) {
            throw new CommonBusiExceptions("没有零件信息");
        }
        Set<String> um = new HashSet<>();
        for (ServiceBorrowOutDetailVO vvo : detailVOs) {
            if (StringUtils.isBlank(vvo.getMaterialsNo())) {
                throw new CommonBusiExceptions("零件号码不能为空");
            }
            if (um.contains(vvo.getMaterialsNo())) {
                throw new CommonBusiExceptions("同一个单据下零件号码不能重复");
            }
            um.add(vvo.getMaterialsNo());
        }
        String orgId = getCompanyOrgIdByCode(serviceBorrowOutVO.getErpCode());
        if (StringUtils.isEmpty(orgId)) {
            throw new CommonBusiExceptions("服务站不存在!");
        }
        return detailVOs;
    }

    private String getCompanyOrgIdByCode(String erpCode) {
        List<String> orgIds = companyDealerMapper.listOrgIdByCode(erpCode, companyUtil.ynOrgId());
        if (CollectionUtils.isEmpty(orgIds)) {
            throw new CommonBusiExceptions("服务站不存在");
        }
        if (orgIds.size() > 1) {
            throw new CommonBusiExceptions("服务站不唯一");
        }
        return orgIds.get(0);
    }

    private void syncInfo(ServiceBorrowOutVO serviceBorrowOutVO, String orgId) {
        if (StringUtils.isEmpty(orgId)) {
            throw new CommonBusiExceptions("服务站不存在");
        }
        ServiceBorrowOutDO serviceBorrowOutDO = new ServiceBorrowOutDO();
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (ErrorCode.Success.getCode() != textResult.getCode()) {
            throw new CommonBusiExceptions(textResult.getMessage());
        }
        String borrowOutId = textResult.getValue();
        serviceBorrowOutDO.setCreateId(null);
        serviceBorrowOutDO.setCreateName("crm");
        serviceBorrowOutDO.setCreateDate(new Date());
        serviceBorrowOutDO.setId(borrowOutId);
        serviceBorrowOutDO.setOrgId(orgId);
        serviceBorrowOutDO.setRepairNo(serviceBorrowOutVO.getRepairNo());
        serviceBorrowOutDO.setWarehouseCode(serviceBorrowOutVO.getWarehouseCode());
        //新增的时候需要保存状态 0-未出库，1-部分出库，2-已出库，3-结单
        serviceBorrowOutDO.setStatus(0);
        serviceBorrowOutDO.setBorrowNo(serviceBorrowOutVO.getBorrowNo());
        serviceBorrowOutDO.setDispatchNo(serviceBorrowOutVO.getDispatchNo());
        serviceBorrowOutDO.setErpCode(serviceBorrowOutVO.getErpCode());
        serviceBorrowOutDO.setEngineNo(serviceBorrowOutVO.getEngineNo());
        serviceBorrowOutMapper.mergeIntoByNo(serviceBorrowOutDO);
    }

//    public PriMaterialsDO convertPriMaterialsDO(MaterialVO materialVO) {
//        String orgId = companyUtil.ynOrgId();
//        PriMaterialsDO materialsDO = new PriMaterialsDO();
//        materialsDO.setMaterialsId(materialVO.getMaterialId());
//        materialsDO.setMaterialsNo(materialVO.getMaterialCode());
//        materialsDO.setMaterialsDes(materialVO.getMaterialName());
//        materialsDO.setUnit(materialVO.getUnitName());
//        materialsDO.setMaterialsMeasure(materialVO.getMaterialSpecs());
//        materialsDO.setMaterialsType(materialVO.getMaterialType());
//        materialsDO.setMaterialsTypeId(materialVO.getMaterialTypeCode());
//        materialsDO.setValidFlag("1".equals(materialVO.getIsStop()) ? Integer.valueOf(1) : Integer.valueOf(0));
//        materialsDO.setOrgId(orgId);
//        materialsDO.setPrice(BigDecimal.ZERO);
//        BigDecimal price = marketingMaterialsMapper.getPriceByMarketType(orgId, materialsDO.getMaterialsNo(), "代理商含税销售价");
//        if (price != null) {
//            materialsDO.setPrice(price);
//        }
//        return materialsDO;
//    }


    /**
     * 根据状态，等信息保存数据
     *
     * @param serviceBorrowOutVO
     * @param userId
     * @param userName
     * @param orgId
     */
    private ErrorCode doSave(ServiceBorrowOutVO serviceBorrowOutVO, String userId, String userName, String orgId) throws Exception {
        preSaveCheck(serviceBorrowOutVO);
        ServiceBorrowOutDO serviceBorrowOutDO = new ServiceBorrowOutDO();
        BeanUtils.copyProperties(serviceBorrowOutVO, serviceBorrowOutDO);
        boolean isAdd = false;
        if (StringUtils.isBlank(serviceBorrowOutVO.getId())) {
            isAdd = true;
            String borrowOutId = commonGenService.textIdWithException();
            serviceBorrowOutDO.setCreateId(userId);
            serviceBorrowOutDO.setCreateName(userName);
            serviceBorrowOutDO.setCreateDate(new Date());
            serviceBorrowOutDO.setId(borrowOutId);
            serviceBorrowOutDO.setOrgId(orgId);
            // 0-未出库，1-部分出库，2-已出库，3-结单
            //新增的时候需要保存状态
            serviceBorrowOutDO.setStatus(0);
            serviceBorrowOutDO.setBorrowNo(genDocumentService.genDocumentNo(BillDesc.ServiceBorrow, orgId));
            logger.info("新增操作，serviceBorrowOutDO:{}", serviceBorrowOutDO);
        } else {
            String borrowOutId = serviceBorrowOutVO.getId();
            serviceBorrowOutDO.setUpdateDate(new Date());
            serviceBorrowOutDO.setUpdateId(userId);
            serviceBorrowOutDO.setId(borrowOutId);
            logger.info("编辑操作，serviceBorrowOutDO:{}", serviceBorrowOutDO);
        }

        //调用详情表的保存逻辑
        List<ServiceBorrowOutDetailVO> serviceBorrowOutDetailVOS = serviceBorrowOutVO.getServiceBorrowOutDetailVOS();
        ServiceBorrowOutDetailVO outDetailCond = new ServiceBorrowOutDetailVO();
        outDetailCond.setBorrowOutId(serviceBorrowOutDO.getId());
        List<ServiceBorrowOutDetailDO> dbDetails = serviceBorrowOutDetailService.queryList(outDetailCond);
        Boolean flag = true;
        UserCacheDTO user = composeUser(userId, userName, orgId);
        flag = doSaveDetails(serviceBorrowOutDetailVOS, flag, serviceBorrowOutDO, dbDetails, isAdd, user);

        if (flag) {
            serviceBorrowOutDO.setStatus(2);
        }
        boolean isSuccess = this.merge(serviceBorrowOutDO) > 0;
        if (!isSuccess) {
            return ErrorCode.Failure;
        }
        //TODO调用出库的相关逻辑
        if (isAdd) {
            return saveWarehouseDeliveryByBorrowInfo(serviceBorrowOutDO, serviceBorrowOutDetailVOS);
        }

        ErrorCode errorCode = delBorrowOutDetail(serviceBorrowOutVO, orgId);
        if (errorCode != null) {
            return errorCode;
        }
        return ErrorCode.Success;
    }

    private UserCacheDTO composeUser(String userId, String userName, String orgId) {
        UserCacheDTO m = new UserCacheDTO();
        m.setUserId(userId);
        m.setName(userName);
        m.setSpaceId(orgId);
        return m;
    }

    private Boolean doSaveDetails(List<ServiceBorrowOutDetailVO> serviceBorrowOutDetailVOS, Boolean flag,
                                  ServiceBorrowOutDO serviceBorrowOutDO, List<ServiceBorrowOutDetailDO> dbDetails,
                                  boolean isAdd, UserCacheDTO user) {
        int seqNo = 0;
        BigDecimal totalAmount = BigDecimal.ZERO;
        String borrowOutId = serviceBorrowOutDO.getId();
        for (ServiceBorrowOutDetailVO outDetailVO : serviceBorrowOutDetailVOS) {
            ++seqNo;
            if (StringUtils.isEmpty(outDetailVO.getId())) {
                outDetailVO.setSeqNo(seqNo);
            }
            //设置主表的ID
            outDetailVO.setBorrowOutId(borrowOutId);
            outDetailVO.setBorrowOutNo(serviceBorrowOutDO.getBorrowNo());
            if (outDetailVO.getQuantity() != null && outDetailVO.getPrice() != null) {
                outDetailVO.setSubtotalAmount(outDetailVO.getPrice().multiply(outDetailVO.getQuantity()));
            } else {
                outDetailVO.setSubtotalAmount(BigDecimal.ZERO);
            }
            totalAmount = totalAmount.add(outDetailVO.getSubtotalAmount());
            if (!isAdd) {
                doSaveDetailsUpdate(outDetailVO, dbDetails);
                flag = flag && (Integer.valueOf(2).equals(outDetailVO.getStatus()));
            } else {
                flag = false;
            }
            try {
                ErrorCode errorCode = serviceBorrowOutDetailService.save(outDetailVO, user.getUserId(), user.getName(), user.getSpaceId());
                if (errorCode.getCode() != 0) {
                    throw new CommonBusiExceptions(errorCode.getDesc());
                }
            } catch (Exception e) {
                throw new CommonBusiExceptions(e.getMessage());
            }
        }
        serviceBorrowOutDO.setTotalAmount(totalAmount);
        return flag;
    }

    private void doSaveDetailsUpdate(ServiceBorrowOutDetailVO outDetailVO, List<ServiceBorrowOutDetailDO> dbDetails) {
        //将页面的借用数量与数据库该记录的已出库数量比较
        Optional<ServiceBorrowOutDetailDO> optionalDetailDO = dbDetails.stream().filter(x -> x.getId().equals(outDetailVO.getId())).findFirst();
        if (optionalDetailDO.isPresent()) {
            if (outDetailVO.getQuantity().compareTo(optionalDetailDO.get().getOutQuantity()) > 0) {
                if (optionalDetailDO.get().getOutQuantity().compareTo(BigDecimal.ZERO) == 0) {
                    outDetailVO.setStatus(0);
                } else {
                    outDetailVO.setStatus(1);
                }
            } else {
                outDetailVO.setStatus(2);
            }
        }
    }

    private ErrorCode delBorrowOutDetail(ServiceBorrowOutVO serviceBorrowOutVO, String orgId) throws Exception {
        List<String> deleteIdList = serviceBorrowOutVO.getDeleteIdList();
        if (null == deleteIdList || deleteIdList.isEmpty()) {
            return null;
        }
        return serviceBorrowOutDetailService.delete(deleteIdList, orgId);
    }

    private ErrorCode updateWarehouseDeliveryByBorrowInfo(ServiceBorrowOutDO serviceBorrowOutDO, List<ServiceBorrowOutDetailVO> serviceBorrowOutDetailVOS) throws Exception {
        warehouseDeliveryDetailMapper.deleteByBusinessOrder(serviceBorrowOutDO.getBorrowNo());
        warehouseDeliveryMapper.deleteByBusinessOrder(serviceBorrowOutDO.getBorrowNo());
        saveWarehouseDeliveryByBorrowInfo(serviceBorrowOutDO, serviceBorrowOutDetailVOS);
        return ErrorCode.Success;
    }

    private ErrorCode saveWarehouseDeliveryByBorrowInfo(ServiceBorrowOutDO serviceBorrowOutDO, List<ServiceBorrowOutDetailVO> serviceBorrowOutDetailVOS) throws Exception {
        //非正常出库添加到出库单
        WarehouseDeliveryDO warehouseDeliveryDO = new WarehouseDeliveryDO();
        ActionResult<String> textDelivery = fastGenClient.textGuid();
        if (textDelivery.getCode() != ErrorCode.Success.getCode()) {
            return ErrorCode.IllegalArument;
        }
        //主键
        warehouseDeliveryDO.setId(textDelivery.getValue());
        //出库单号
        warehouseDeliveryDO.setDeliveryOrder(genDocumentService.genDocumentNo(BillDesc.OutputNo, serviceBorrowOutDO.getOrgId()));
        //业务单号（借用单号）
        warehouseDeliveryDO.setBusinessOrder(serviceBorrowOutDO.getBorrowNo());
        //业务单别（借用单单别）
        warehouseDeliveryDO.setBusinessSingle(BillDesc.ServiceBorrow.getDesc());
        //备注
        warehouseDeliveryDO.setNote(serviceBorrowOutDO.getRemark());
        //创建人
        warehouseDeliveryDO.setCreaterId(serviceBorrowOutDO.getCreateId());
        warehouseDeliveryDO.setCreaterName(serviceBorrowOutDO.getCreateName());
        //状态
        warehouseDeliveryDO.setStatus(0);
        //创建时间
        warehouseDeliveryDO.setCreateDate(new Date());
        warehouseDeliveryDO.setOrgId(serviceBorrowOutDO.getOrgId());
        warehouseDeliveryDO.setWarehouseCode(serviceBorrowOutDO.getWarehouseCode());
        for (ServiceBorrowOutDetailVO serviceBorrowOutDetailVO : serviceBorrowOutDetailVOS) {
            WarehouseDeliveryDetailDO warehouseDeliveryDetailDO = new WarehouseDeliveryDetailDO();
            ActionResult<String> textDeliveryDetail = fastGenClient.textGuid();
            if (textDeliveryDetail.getCode() != ErrorCode.Success.getCode()) {
                return ErrorCode.IllegalArument;
            }
            warehouseDeliveryDetailDO.setId(textDeliveryDetail.getValue());
            warehouseDeliveryDetailDO.setDeliveryOrder(warehouseDeliveryDO.getDeliveryOrder());
            warehouseDeliveryDetailDO.setBusinessSingle(BillDesc.ServiceBorrow.getDesc());
            warehouseDeliveryDetailDO.setBusinessOrder(serviceBorrowOutDO.getBorrowNo());
            warehouseDeliveryDetailDO.setMaterialNo(serviceBorrowOutDetailVO.getMaterialsNo());
            warehouseDeliveryDetailDO.setRealAmount(new BigDecimal(0));
            warehouseDeliveryDetailDO.setAmount(serviceBorrowOutDetailVO.getQuantity());
            warehouseDeliveryDetailDO.setUnit(serviceBorrowOutDetailVO.getUnit());
            warehouseDeliveryDetailDO.setCreaterId(serviceBorrowOutDO.getCreateId());
            warehouseDeliveryDetailDO.setCreaterName(serviceBorrowOutDO.getCreateName());
            warehouseDeliveryDetailDO.setCreateDate(new Date());
            warehouseDeliveryDetailDO.setMaterialName(serviceBorrowOutDetailVO.getMaterialsDes());
            warehouseDeliveryDetailDO.setStatus(0);
            warehouseDeliveryDetailDO.setOrgId(serviceBorrowOutDO.getOrgId());
            warehouseDeliveryDetailMapper.insert(warehouseDeliveryDetailDO);
        }
        warehouseDeliveryMapper.insert(warehouseDeliveryDO);

        return ErrorCode.Success;
    }

    /**
     * 保存前信息校验
     */
    private void preSaveCheck(ServiceBorrowOutVO serviceBorrowOutVO) {
        if (null == serviceBorrowOutVO) {
            throw new CommonBusiExceptions(ErrorCode.IllegalArument.getDesc());
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public int merge(ServiceBorrowOutDO dto) {
        return serviceBorrowOutMapper.merge(dto);
    }

    /**
     * 删除
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode delete(String id, String orgId) {
        //先判断当前出库状态是否可以删除
        //0-未出库，1-部分出库，2-已出库，3-结单
        ServiceBorrowOutVO serviceBorrowOutVO = queryById(id, orgId);
        if (null != serviceBorrowOutVO.getStatus() && serviceBorrowOutVO.getStatus() != 0) {
            return ErrorCode.ServiceBorrowOutInfoStatusIsFalse;
        }
        if (id.isEmpty()) {
            return ErrorCode.Failure;
        }
        //删除借用单信息
        int i = serviceBorrowOutMapper.deleteByPrimaryKeySelective(id);
        if (i == 0) {
            throw new CommonBusiExceptions(ErrorCode.Failure.getDesc());
        }
        deleteDetails(id);

        //删除入库信息
        List<String> orderList = Lists.newArrayList();
        orderList.add(serviceBorrowOutVO.getBorrowNo());
        warehouseDeliveryService.removeByBusinessOrders(orderList, orgId);
        return ErrorCode.Success;
    }

    /**
     * 根据借用单信息删除借用单详情信息
     *
     * @param id
     * @
     */
    private void deleteDetails(String id) {
        //查询借用单详情信息
        ServiceBorrowOutDetailVO serviceBorrowOutDetailVO = new ServiceBorrowOutDetailVO();
        serviceBorrowOutDetailVO.setBorrowOutId(id);
        List<ServiceBorrowOutDetailDO> serviceBorrowOutDetailDOS = serviceBorrowOutDetailService.queryList(serviceBorrowOutDetailVO);
        List<String> detailIds = new ArrayList<>();
        for (ServiceBorrowOutDetailDO detailDO : serviceBorrowOutDetailDOS) {
            detailIds.add(detailDO.getId());
        }
        try {
            //删除借用单详情信息  ErrorCode errorCode =
            serviceBorrowOutDetailService.batchDelete(detailIds);
        } catch (Exception e) {
            throw new CommonBusiExceptions(e.getMessage());
        }
        //释放占用的借款额度
    }

    /**
     * 手动完成单据<br>
     * materialsNo 不为null,则更改该单据下的零件状态为“手动完成”状态；如果materialsNo为空，则更改整个单据为“手动完成”状态
     *
     * @param billNo      String 单据编号
     * @param materialsNo String 零件编号
     * @param orgId       String 企业ID
     * @return ErrorCode 返回码
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode manualFinish(String billNo, String materialsNo, String orgId) {
        ServiceBorrowOutDO selectByBorrowNo = serviceBorrowOutMapper.selectByBorrowNo(billNo, orgId);
        //零件编码为空，更新单据状态为“手动完成”
        if (StringUtil.isNullOrEmpty(materialsNo)) {
            //借用单结单
            selectByBorrowNo.setStatus(3);
            serviceBorrowOutMapper.updateByPrimaryKeySelective(selectByBorrowNo);
            warehouseDeliveryService.updateState(billNo, 3, orgId);
            serviceBorrowOutDetailMapper.updateStatus(3, selectByBorrowNo.getId(), materialsNo, orgId);
            warehouseDeliveryDetailMapper.updateAllStatus(3, billNo, orgId);
        } else {
            serviceBorrowOutDetailMapper.updateStatus(3, selectByBorrowNo.getId(), materialsNo, orgId);
            warehouseDeliveryService.updateDetailState(billNo, materialsNo, null, 3, orgId);
            ErrorCode errorCode = checkBillFinished(selectByBorrowNo, orgId);

            if (ErrorCode.Success != errorCode) {
                throw new CommonBusiExceptions("更新失败");
            }
        }
        return ErrorCode.Success;
    }

    /**
     * 校验单据是否已完成<br>
     * 判断单据下的所有零件是否已经完成，如果都完成，则更改单据状态为完成
     *
     * @param serviceBorrowOutDO selectByBorrowN
     * @param orgId              String
     * @return Boolean
     */
    private ErrorCode checkBillFinished(ServiceBorrowOutDO serviceBorrowOutDO, String orgId) {
        ServiceBorrowOutDetailVO condition = new ServiceBorrowOutDetailVO();
        condition.setBorrowOutId(serviceBorrowOutDO.getId());
        List<ServiceBorrowOutDetailDO> detailDOs = serviceBorrowOutDetailMapper.queryList(condition);
        if (ListUtil.isNullOrEmpty(detailDOs)) {
            throw new CommonBusiExceptions("未查询到服务借用单详情列表信息");
        }
        boolean manul = false;
        boolean flag = true;
        int status;
        for (ServiceBorrowOutDetailDO temp : detailDOs) {
            if (temp.getStatus() == 3) {
                manul = true;
            }
            if (2 == temp.getStatus() || 3 == temp.getStatus()) {
                //完成状态
                continue;
            }
            flag = false;
        }
        if (flag) {
            if (manul) {
                status = 3;
            } else {
                status = 2;
            }
        } else {
            status = 1;
        }
        //借用单结单
        ServiceBorrowOutDO updateBorrowNo = new ServiceBorrowOutDO();
        updateBorrowNo.setId(serviceBorrowOutDO.getId());
        updateBorrowNo.setStatus(status);
        serviceBorrowOutMapper.updateByPrimaryKeySelective(updateBorrowNo);
        warehouseDeliveryService.updateState(serviceBorrowOutDO.getBorrowNo(), status, orgId);
        return ErrorCode.Success;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean updateByOutbound(String threeOrder, String materialNo, BigDecimal realAmount,
                                    Integer singelState, Integer totalState, String orgId, boolean updateReceipt) {
        ServiceBorrowOutVO outVO = new ServiceBorrowOutVO();
        outVO.setOrgId(orgId);
        outVO.setBorrowNo(threeOrder);
        List<ServiceBorrowOutDO> outDOList = queryList(outVO);
        if (ListUtil.isNullOrEmpty(outDOList)) {
            throw new CommonBusiExceptions("未找到单据记录");
        }
        ServiceBorrowOutDO outDO = outDOList.get(0);

        ServiceBorrowOutDetailVO detailCond = new ServiceBorrowOutDetailVO();
        detailCond.setBorrowOutId(outDO.getId());
        detailCond.setMaterialsNo(materialNo);
        List<ServiceBorrowOutDetailDO> detailDOList = serviceBorrowOutDetailService.queryList(detailCond);

        if (detailDOList.size() == 0) {
            throw new CommonBusiExceptions("未找到详情记录");
        }
        ServiceBorrowOutDetailDO detailDO = detailDOList.get(0);
        detailDO.setOutQuantity(realAmount);
        detailDO.setStatus(singelState);
        boolean success = serviceBorrowOutDetailMapper.updateByPrimaryKeySelective(detailDO) > 0;
        if (success) {
            ServiceBorrowOutDO outStatusDO = new ServiceBorrowOutDO();
            outStatusDO.setId(outDO.getId());
            outStatusDO.setStatus(Integer.valueOf(totalState));
            success = serviceBorrowOutMapper.updateByPrimaryKeySelective(outStatusDO) > 0;
        }
        if (success) {
            //添加个人出库零件信息
            ServiceBorrowingVO serviceBorrowingVO = new ServiceBorrowingVO();
            serviceBorrowingVO.setOrgId(outDO.getOrgId());
            serviceBorrowingVO.setUserId(outDO.getServiceStaffId());
            serviceBorrowingVO.setUserName(outDO.getServiceStaffName());
            serviceBorrowingVO.setMaterialsNo(detailDO.getMaterialsNo());
            serviceBorrowingVO.setMaterialsDes(detailDO.getMaterialsDes());
            serviceBorrowingVO.setUnit(detailDO.getUnit());
            serviceBorrowingVO.setPrice(detailDO.getPrice());
            serviceBorrowingVO.setQuantity(realAmount);
            success = serviceBorrowingService.save(serviceBorrowingVO).equals(ErrorCode.Success);
        }


        return success;
    }


    public void export(List<String> abnormalOutIds) {
        List<ServiceBorrowOutVO> voList = new ArrayList<>();
        for (String abnormalOutId : abnormalOutIds) {
            ServiceBorrowOutDO entity = serviceBorrowOutMapper.item(abnormalOutId);
            ServiceBorrowOutVO model = new ServiceBorrowOutVO();
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        invokeExport(voList);
    }

    public void exportAll(ServiceBorrowOutVO condition) {
        //PageHelperPlus.startPage(0, 0, "id desc");
        List<ServiceBorrowOutVO> voList = new ArrayList<>();
        List<ServiceBorrowOutDO> doList = serviceBorrowOutMapper.queryList(condition);
        for (ServiceBorrowOutDO entity : doList) {
            ServiceBorrowOutVO model = new ServiceBorrowOutVO();
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        invokeExport(voList);
    }

    private void invokeExport(List<ServiceBorrowOutVO> voList) {
        String title = "服务借用数据导出";
        String[] rowsName = new String[]{"序号", "服务人员借用单号", "制单人", "制单时间", "服务人员", "发出仓库", "客户名称", "原因", "派工单号", "备注",
                "出库状态",
                "零件编码", "零件名称", "单位", "借用数量", "出库数量", "出库状态", "单价"};
        List<Object[]> dataList = new ArrayList<>();
        Object[] objs;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (int i = 0; i < voList.size(); i++) {
            ServiceBorrowOutVO billInfo = voList.get(i);
            ServiceBorrowOutDetailVO detailCond = new ServiceBorrowOutDetailVO();
            detailCond.setBorrowOutId(billInfo.getId());
            List<ServiceBorrowOutDetailDO> detailDOList = serviceBorrowOutDetailMapper.queryList(detailCond);
            for (ServiceBorrowOutDetailDO detailDO : detailDOList) {
                objs = new Object[rowsName.length];
                objs[0] = i + 1;
                objs[1] = billInfo.getBorrowNo();
                objs[2] = billInfo.getCreateName();
                objs[3] = sdf.format(billInfo.getCreateDate());
                objs[4] = billInfo.getServiceStaffName();
                objs[5] = billInfo.getWarehouseCode();
                objs[6] = billInfo.getCustomerName();
                objs[7] = billInfo.getReason();
                objs[8] = billInfo.getDispatchNo();
                objs[9] = billInfo.getRemark();
                objs[10] = getStatusDesc(detailDO.getStatus());
                objs[11] = detailDO.getMaterialsNo();
                objs[12] = detailDO.getMaterialsDes();
                objs[13] = detailDO.getUnit();
                objs[14] = detailDO.getQuantity();
                objs[15] = detailDO.getOutQuantity();
                objs[16] = getStatusDesc(detailDO.getStatus());
                objs[17] = detailDO.getPrice();
                dataList.add(objs);
            }

        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getStatusDesc(Integer statusId) {
        switch (statusId) {
            case 0:
            case 1:
                return "部分出库";
            case 2:
                return "已出库";
            case 3:
                return "强制结单";
            default:
                return "未出库";
        }

    }

    public ServiceBorrowInAddVO queryByBorrowOutNo(String borrowOutNo, String orgId, String userId, String userName) {
        ServiceBorrowInAddVO serviceBorrowInAddVO = new ServiceBorrowInAddVO();
        ServiceBorrowOutDO serviceBorrowOutDO = serviceBorrowOutMapper.selectByBorrowNo(borrowOutNo, orgId);
        if (null == serviceBorrowOutDO) {
            return serviceBorrowInAddVO;
        }
        ServiceBorrowInVO serviceBorrowInVO = new ServiceBorrowInVO();
        serviceBorrowInVO.setBorrowOutNo(serviceBorrowOutDO.getBorrowNo());
        serviceBorrowInVO.setCreateName(userName);
        serviceBorrowInVO.setCreateId(userId);
        serviceBorrowInVO.setCreateDate(new Date());
        serviceBorrowInVO.setServiceStaffId(serviceBorrowOutDO.getServiceStaffId());
        serviceBorrowInVO.setServiceStaffName(serviceBorrowOutDO.getServiceStaffName());
        serviceBorrowInVO.setCustomerId(serviceBorrowOutDO.getCustomerId());
        serviceBorrowInVO.setCustomerName(serviceBorrowOutDO.getCustomerName());
        serviceBorrowInVO.setWarehouseCode(serviceBorrowOutDO.getWarehouseCode());
        serviceBorrowInAddVO.setServiceBorrowInVO(serviceBorrowInVO);

        BigDecimal totalPrice = BigDecimal.ZERO;
        List<ServiceBorrowOutDetailDO> borrowOutDetailDOList = serviceBorrowOutDetailMapper.selectByBorrowNo(serviceBorrowOutDO.getId());
        if (null != borrowOutDetailDOList && !borrowOutDetailDOList.isEmpty()) {
            List<ServiceBorrowInDetailVO> detailVOList = new ArrayList<>();
            for (ServiceBorrowOutDetailDO outDetailDO : borrowOutDetailDOList) {
                ServiceBorrowInDetailVO detailVO = new ServiceBorrowInDetailVO();
                detailVO.setBorrowOutDetailId(outDetailDO.getId());
                detailVO.setMaterialsNo(outDetailDO.getMaterialsNo());
                detailVO.setMaterialsDes(outDetailDO.getMaterialsDes());
                detailVO.setUnit(outDetailDO.getUnit());
                detailVO.setThisReturnQty(BigDecimal.ZERO);//本单已退回
                BigDecimal borrowOutboundQty = outDetailDO.getOutQuantity();
                detailVO.setBorrowOutboundQty(borrowOutboundQty);//借用出库数量
                BigDecimal resaleQty = outDetailDO.getResaleQty();
                resaleQty = resaleQty == null ? BigDecimal.ZERO : resaleQty;
                detailVO.setResaleQty(resaleQty);//转销售数量
                BigDecimal createBorrowInQty = outDetailDO.getRollBackQty();
                BigDecimal returnQty = borrowOutboundQty.subtract(getValueDefaultZero(createBorrowInQty)).subtract(resaleQty);
                if (null == returnQty || returnQty.compareTo(BigDecimal.ZERO) == 0) {//筛选掉可退回数量为0的数据
                    continue;
                }
                detailVO.setReturnQty(returnQty); //退回数量
                //根据借用单号获取退回的数量
                BigDecimal borrowReturnQty = serviceBorrowInDetailMapper.queryThisReturnQty(outDetailDO.getId(), outDetailDO.getMaterialsNo());
                borrowReturnQty = borrowReturnQty == null ? BigDecimal.ZERO : borrowReturnQty;
                detailVO.setBorrowReturnQty(borrowReturnQty); //借用单退回数
                detailVO.setPrice(outDetailDO.getPrice());
                detailVO.setRemark(outDetailDO.getRemark());
                BigDecimal price = outDetailDO.getPrice();
                totalPrice = totalPrice.add(price.multiply(returnQty).setScale(2, BigDecimal.ROUND_DOWN));
                detailVOList.add(detailVO);
            }
            serviceBorrowInAddVO.setDetailVOList(detailVOList);
        }
        serviceBorrowInVO.setTotalPrice(totalPrice);
        return serviceBorrowInAddVO;
    }

    //更新转退回数量
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRollBackQty(String borrowOutDetailId, BigDecimal realAmount, BigDecimal oldRealAmount) {
        ServiceBorrowOutDetailDO serviceBorrowOutDetailDO = serviceBorrowOutDetailMapper.selectByPrimaryKey(borrowOutDetailId);
        if (null == serviceBorrowOutDetailDO) {
            return false;
        }

        BigDecimal rollBackQty = serviceBorrowOutDetailDO.getRollBackQty() == null ? BigDecimal.ZERO : serviceBorrowOutDetailDO.getRollBackQty();
        if (null != oldRealAmount && oldRealAmount.compareTo(BigDecimal.ZERO) != 0) {
            rollBackQty = rollBackQty.subtract(oldRealAmount).add(realAmount);
        } else {
            rollBackQty = rollBackQty.add(realAmount);
        }

        ServiceBorrowOutDetailDO updateDetailDO = new ServiceBorrowOutDetailDO();
        updateDetailDO.setRollBackQty(rollBackQty);
        updateDetailDO.setId(borrowOutDetailId);
        boolean success = serviceBorrowOutDetailMapper.updateByPrimaryKeySelective(updateDetailDO) > 0;
        if (success) {
            String borrowOutId = serviceBorrowOutDetailDO.getBorrowOutId();
            int count = serviceBorrowOutDetailMapper.checkResaleQtyRollBackQty(borrowOutId);
            ServiceBorrowOutDO bean = new ServiceBorrowOutDO();
            bean.setId(borrowOutId);
            if (count <= 0) {
                bean.setOrderStatus(1);
            } else {
                bean.setOrderStatus(0);
            }
            success = serviceBorrowOutMapper.updateByPrimaryKeySelective(bean) > 0;
        }

        return success;
    }

    public BigDecimal getRemainingQty(String borrowNo, String materialNo, String orgId) {
        if (StringUtils.isBlank(borrowNo)) {
            return null;
        }
        ServiceBorrowOutDO serviceBorrowOutDO = serviceBorrowOutMapper.selectByBorrowNo(borrowNo, orgId);
        if (null == serviceBorrowOutDO) {
            return null;
        }
        return serviceBorrowOutDetailMapper.getRemainingQty(serviceBorrowOutDO.getId(), materialNo);
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean updateResaleQty(String borrowNo, String materialNo, String orgId, BigDecimal adjustedQty, BigDecimal oldAdjustedQty) {
        ServiceBorrowOutDO serviceBorrowOutDO = serviceBorrowOutMapper.selectByBorrowNo(borrowNo, orgId);
        ServiceBorrowOutDetailVO condition = new ServiceBorrowOutDetailVO();
        condition.setBorrowOutId(serviceBorrowOutDO.getId());
        condition.setMaterialsNo(materialNo);
        List<ServiceBorrowOutDetailDO> borrowOutDetailDOList = serviceBorrowOutDetailMapper.queryList(condition);
        if (null == borrowOutDetailDOList || borrowOutDetailDOList.isEmpty()) {
            return false;
        }

        ServiceBorrowOutDetailDO serviceBorrowOutDetailDO = borrowOutDetailDOList.get(0);
        BigDecimal resaleQty = serviceBorrowOutDetailDO.getResaleQty() == null ? BigDecimal.ZERO : serviceBorrowOutDetailDO.getResaleQty();
        if (null != oldAdjustedQty && oldAdjustedQty.compareTo(BigDecimal.ZERO) != 0) {
            resaleQty = resaleQty.subtract(oldAdjustedQty).add(adjustedQty);
        } else {
            resaleQty = resaleQty.add(adjustedQty);
        }

        ServiceBorrowOutDetailDO updateDetailDO = new ServiceBorrowOutDetailDO();
        updateDetailDO.setResaleQty(resaleQty);
        updateDetailDO.setId(serviceBorrowOutDetailDO.getId());
        boolean success = serviceBorrowOutDetailMapper.updateByPrimaryKeySelective(updateDetailDO) > 0;
        if (success) {
            String borrowOutId = serviceBorrowOutDO.getId();
            int count = serviceBorrowOutDetailMapper.checkResaleQtyRollBackQty(borrowOutId);
            ServiceBorrowOutDO bean = new ServiceBorrowOutDO();
            bean.setId(borrowOutId);
            if (count <= 0) {
                bean.setOrderStatus(1);
            } else {
                bean.setOrderStatus(0);
            }
            success = serviceBorrowOutMapper.updateByPrimaryKeySelective(bean) > 0;
        }

        return success;
    }

    @Transactional
    public void outStock(String id, String userId, String orgId) {
        ServiceBorrowOutDO serviceBorrowOutDO = serviceBorrowOutMapper.item(id);
        if (StringUtils.isNotEmpty(serviceBorrowOutDO.getRepairNo())) {
            throw new CommonBusiExceptions("没有报修单号");
        }
        ServiceBorrowOutDetailVO condition = new ServiceBorrowOutDetailVO();
        condition.setBorrowOutId(id);
        List<ServiceBorrowOutDetailDO> detailDOs = serviceBorrowOutDetailService.queryList(condition);
        List<RepairDO> repairDOs = repairService.itemByCode(serviceBorrowOutDO.getRepairNo());
        Map<String, List<String>> barCodeMap = new HashMap<>();
        for (RepairDO repairDO : repairDOs) {
            List<String> barCodes = barCodeMap.get(repairDO.getMaterialsNo());
            if (CollectionUtils.isEmpty(barCodes)) {
                barCodes = new ArrayList<>();
                barCodeMap.put(repairDO.getMaterialsNo(), barCodes);
            }
            barCodes.add(repairDO.getBarCode());
        }

        for (ServiceBorrowOutDetailDO detailDO : detailDOs) {
            String materialsNo = detailDO.getMaterialsNo();
            BigDecimal quantity = detailDO.getQuantity();
            List<String> barCodes = barCodeMap.get(materialsNo);
            if (CollectionUtils.isNotEmpty(barCodes)) {
                outStockInfo(serviceBorrowOutDO.getBorrowNo(), materialsNo, quantity, barCodes, userId, orgId);
            }
        }
    }

    public BigDecimal outStockInfo(String billNo, String materialsNo, BigDecimal quantity, List<String> barCodes, String userId, String orgId) {
        BigDecimal lastQuantity = quantity;
        logger.info("{}", materialsNo);
        for (String barCode : barCodes) {
            if (lastQuantity.compareTo(BigDecimal.ZERO) > 0) {
                WarehouseInventoryDO warehouseInventoryDO = warehouseInventoryMapper.selectByBarCode(barCode, orgId);
                BigDecimal inventoryQuantity = warehouseInventoryDO.getAmount();
                BigDecimal splitQuantity = lastQuantity;
                if (lastQuantity.compareTo(inventoryQuantity) >= 0) {
                    splitQuantity = inventoryQuantity;
                }
                WarehouseDeliveryRecordAddVO warehouseDeliveryRecordAddVO = new WarehouseDeliveryRecordAddVO();
                warehouseDeliveryRecordAddVO.setAmount(quantity);
                warehouseDeliveryRecordAddVO.setBarCode(barCode);
                warehouseDeliveryRecordAddVO.setBusinessOrder(billNo);
                warehouseDeliveryRecordAddVO.setSplitAmount(splitQuantity);
                try {
                    warehouseDeliveryRecordService.add(warehouseDeliveryRecordAddVO, userId, orgId, true, false);
                } catch (Exception e) {
                    throw new CommonBusiExceptions(e.getMessage());
                }
            }
        }
        return BigDecimal.ZERO;
    }
}
